home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
C_TUTR24.ARJ
/
LESSON10
< prev
next >
Wrap
Text File
|
1986-03-21
|
14KB
|
354 lines
.NT
A NOTE ABOUT THE LESSONS in C
.b4-24R5C4
These were written while the author was ~Ilearning~N the language and since
.R6C4
they are ~Ifree~N ( to copy and/or distribute ) there is a money-back
.R7C4
guarantee on the accuracy of each and every statement in the lessons (!)
.R9C4
The ~Idisplay~N program was written ( in C ) in order to provide a vehicle
.R10C4
for displaying the lessons.
.R12C5
.B
P.J.Ponzo
.B
Dept. of Applied Math
.B
Univ. of Waterloo
.B
Ontario N2L 3G1
.K16,32
PonzoTUTOR
.WNT
the C PREPROCESSOR
.R4C1
~b~IBEGIN ~N ~b~Imain() { ~N
~b~I DECLARE_AN_INTEGER x; ~N ~b~I int x; ~N
~b~I LET x=0; ~N ~b~I x=0; ~N
~b~I AS_LONG_AS ( x IS_LESS_THAN 5 ) DO ~N ~b~I while (x<5) { ~N
~b~I LET x INCREASE_BY 1; ~N ~b~I x+=1; ~N
~b~I PRINT_x; ~N ~b~I printf("%d",x); ~N
~b~I THEN_STOP ~N ~b~I } ~N
~b~IEND ~N ~b~I} ~N
Wouldn't it be nice if we could write the Left-Hand program (above) and
have it (magically) turn itself into the Right-Hand program?
.WK16,60
GOOD LUCK!
.W
This would require the following ~Idefinitions~N:
define ~b~IBEGIN~N to mean ~b~Imain() {~N
define ~b~IDECLARE_AN_INTEGER~N to mean ~b~Iint~N
define ~b~ILET~N to mean (nothing!)
define ~b~IAS_LONG_AS~N to mean ~b~Iwhile~N
define ~b~IIS_LESS_THAN~N to mean ~b~I<~N
define ~b~IDO~N to mean ~b~I{~N
define ~b~IINCREASE_BY~N to mean ~b~I+=~N
define ~b~IPRINT_x~N to mean ~b~Iprintf("%d",x)~N
define ~b~ITHEN_STOP~N to mean ~b~I}~N
define ~b~IEND~N to mean ~b~I}~N
.WN
One fascinating aspect of the ~IC~N language is its ability to perform
replacements of ~b~IBEGIN~N by ~b~Imain() {~N, and ~b~ILET~N by
nothing (a "null string") and ~b~IEND~N by ~b~I}~N, etc. etc.
Before the C-compiler goes to work on your program, a ~IC-preprocessor~N
will make the appropriate replacements ... and (MAGIC!) the compiler gets
a normal, standard, C program to compile.
To tell the preprocessor that you have redefined certain C-phrases, you
need only ~Ibegin~N your program with these ~I#definitions~N.
.WK16,32
beg
pardon?
.WNT
#define THIS and THAT
.R4C1
~b~I#define BEGIN main() { ~N
~b~I#define DECLARE_AN_INTEGER int ~N
~b~I#define LET ~N
~b~I#define AS_LONG_AS while ~N
~b~I#define IS_LESS_THAN < ~N
~b~I#define INCREASE_BY += ~N
~b~I#define PRINT_x printf("%d",x) ~N
~b~I#define THEN_STOP } ~N
~b~I#define END } ~N
~b~I ~N
~b~IBEGIN ~N
~b~I DECLARE_AN_INTEGER x; ~N
~b~I LET x=0; ~N
~b~I AS_LONG_AS ( x IS_LESS_THAN 5 ) DO ~N
~b~I PRINT_x; ~N
~b~I THEN_STOP ~N
~b~IEND ~N
.w
If the above program is written and compiled, the preprocessor will make
all replacements indicated by the various ~b~I#define~N statements!
.WK5,60
MAGIC!
.WN
The ~b~I#define~N statements are instructions to the ~Ipreprocessor~N.
We've actually seen such instructions before!
Remember ~b~I#include <stdio.h>~N ??
THAT was ~Ialso~N an instruction to the preprocessor .. to replace the phrase,
~b~I#include <stdio.h>~N by the library of standard input/output routines.
( .. which explains why a compiled program is often very much larger than
the program we write with our favourite text-editor .. it contains the
~Ii/o~N library of functions!)
.K16,32
I C!
.WNT
#include <stdio.h> and #include <math.h>
.R5C1
Since ~IC~N is supposed to be a ~IPORTABLE~N language (write a C program
on your favourite text-editor and compile if for ANY computer for which
you have a compiler), the ~Ist~Nan~Id~Nard ~Ii~Nput/~Io~Nutput routines
are system dependent ... and not, strictly speaking, part of the language!
Somebody has written the functions in ~Istdio.h~N with a specific computer
in mind.
.R12C1
... which reminds me ... the library of MATH functions (such as ~b~Isin()~N)
is NOT in ~Istdio.h~N. If you use them, be sure to ~b~I#include <math.h>~N.
.b11-14
.K16,23
NOW he
.K16,37
tells me!
.WNT
even sexier #definitions
.R5C1
In the previous example we used:
~b~I#define PRINT_x printf("%d",x) ~N
which meant that, to ~Iprint y~N or ~Iprint a~N etc. we would need more
#definitions (like PRINT_y and PRINT_a).
~IBUT~N, C is very smart. You can include a ~IVARIABLE~N in the
#definition (within parentheses!), for example:
~b~I#define PRINT(x) printf("%d",x) ~N
... and now use ~b~IPRINT(y)~N or ~b~IPRINT(a)~N etc and the
preprocessor would make the substitutions to ~b~Iy~N or ~b~Ia~N.
.K19,60
NOTE: ()
.WNT
SUGAR for the kids
.R5C1
QUESTION: How to teach programming to kids?
ANSWER: Invent your own kiddie-C!
Let the kids write this but have the C-compiler get this
~b~IBEGIN ~N ~b~Imain() { ~N
~b~I LET x=0; ~N ~b~I int x=0; ~N
~b~I IF (x LESS 10) DO ~N ~b~I while (x<10) { ~N
~b~I PRINT(x); ~N ~b~I printf(" %d ",x); ~N
~b~I PRINT(SQUARE(x)); ~N ~b~I printf(" %d ",x*x); ~N
~b~I NEWLINE; ~N ~b~I printf("\n"); ~N
~b~I INCREASE(x); ~N ~b~I x+=1; ~N
~b~I ENDIF ~N ~b~I } ~N
~b~ISTOP ~N ~b~I} ~N
.W
... can you see what ~I#definitions~N are necessary ???
.WN
These #definitions:
~b~I#define BEGIN main() { ~N
~b~I#define LET int ~N
~b~I#define IF while ~N
~b~I#define LESS < ~N
~b~I#define DO { ~N
~b~I#define PRINT(x) printf(" %d ",x) ~N
~b~I#define SQUARE(x) x*x ~N
~b~I#define NEWLINE printf("\n") ~N
~b~I#define INCREASE(x) x+=1 ~N
~b~I#define ENDIF } ~N
~b~I#define STOP } ~N
turn this into this
~b~IBEGIN ~N ~b~Imain() { ~N
~b~I LET x=0; ~N ~b~I int x=0; ~N
~b~I IF (x LESS 10) DO ~N ~b~I while (x<10) { ~N
~b~I PRINT(x); ~N ~b~I printf(" %d ",x); ~N
~b~I PRINT(SQUARE(x)); ~N ~b~I printf(" %d ",x*x); ~N
~b~I NEWLINE; ~N ~b~I printf("\n"); ~N
~b~I INCREASE(x); ~N ~b~I x+=1; ~N
~b~I ENDIF ~N ~b~I } ~N
~b~ISTOP ~N ~b~I} ~N
.WN
Of course the kids would have to type in all those !@#$% #definitions!!!
... or would they ??
We (the master over~IC~Ner) would have all those !@#$% #definitions!!!
in a separate file (on disk) called ~Isugar.c~N so the kids would only
have to begin their program with: ~b~I#include <sugar.c>~N
The preprocessor would ~b~I#include~N all those !@#$% #definitions!!!
at the beginning of every program, then make all the appropriate
substitutions/replacements ...
.K16,32
SUGAR!
.WN
We have written the #definitions using CAPITALS to replace C-phrases.
That's not necessary, but ADVISABLE! ( then it's obvious which parts of
your program are HOME-MADE and which are "real C")
Not only do #definitions allow us to write ~IC~N in a personal dialect,
but they also allow us to quickly change certain C-phrases.
.K16,32
you C?
.WNT
notes from the author
.R4C1
On the IBM PC (with the "ansi.sys" program installed), I can clear the
screen by using : ~b~Iprintf("?[2J");~N
In place of the question mark, I type an "escape character"
by holding down the ~IAlt~N key and typing the number ~I27~N on the
number pad ... and the "left-arrow" appears when I release the Alt key.
(I can't do it HERE, in this lesson, 'cause it would clear the screen!!)
Now, I begin my programs with a #definition (among others)
~b~I#define CLEAR printf("?[2J")~N
then I can use ~b~ICLEAR;~N wherever I need it, in my program.
Tomorrow, when I buy a sexier C-compiler for the PC (or learn more ~IC~N!)
... one which has all the features included in "ansi.sys" ... including a
~b~Iclr_screen()~N function, I replace the above #definition by:
~b~I#define CLEAR clr_screen()~N
.WK19,60
that
IS
nice
.WNT
typedefinitions
.R5C1
You begin your program with ~b~I#define SAM int~N and it will be
~Ipreprocessed~N, and every occurrence of ~b~ISAM~N will be replaced by
~b~Iint~N ... as in ~b~ISAM x=0;~N which gets passed on to the compiler
(by the preprocessor) as ~b~Iint x=0;~N
This "replacement" by the preprocessor holds for anything ... not just
DATA TYPES ( so ~b~I#define NewLinePlease printf("\n")~N allows you to
use ~b~INewLinePlease;~N in place of ~b~Iprintf("\n");~N ).
BUT, there is a "special" feature for DATA TYPES, called ~b~Itypedef~N.
Place, at the beginning of your program:
~b~Itypedef int INCHES~N (note the order!)
... and you may subsequently use, in your program:
~b~IINCHES x, y, z;~N
.w
and the variables ~b~Ix~N, ~b~Iy~N and ~b~Iz~N will be regarded (by the compiler)
as ~b~Iint~N variables.
.K16,60
what's
NEW?
.WN
Hmmmm ...
~b~Itypedef int INCHES~N (note the order!)
doesn't seem like it's any different from
~b~I#define INCHES int~N (note the order!)
BUT, remember the curious way we had to refer to an argument, passed to a
function, which was ~Iitself~N a function?
~b~Ifloat solve(f,x,error)~N
~b~Ifloat (*f)(); ~N (note the curiosity!)
~b~Ifloat x, error; ~N
~b~I{ ~N
Here, the C-phrase ~b~Ifloat (*f)();~N, says that ~b~If~N is a ~Ipointer~N
to a ~Ifunction~N, and this function returns a ~Ifloat~N.
.WN
~b~Ifloat solve(f,x,error) ~N
~b~Ifloat (*f)(); ~N (note the curiosity!)
~b~Ifloat x, error; ~N
~b~I{ ~N
Now, using ~b~Itypedef~N, we may introduce a home-made DATA TYPE called
~IPointer to a Function which returns a Float~N.
~b~Itypedef float (*PFF)()~N (note the order!)
Use the above ~b~Itypedef~N (near the beginning of your program) and
(MAGIC!) the phrase ~b~IPFF~N is interpreted (by the compiler) as meaning a
~IPointer to a Function which returns a Float~N.
Use it, in ~b~Isolve()~N, like so:
.w
~b~Ifloat solve(f,x,error) ~N
~b~IPFF f; ~N
~b~Ifloat x, error; ~N
~b~I{ ~N
.K19,60
nice eh?
.WN
.R10C1
Since ~b~Itypedef~N is more than "just a dumb replacement of characters",
the preprocessor won't touch it ... but passes it along to the compiler!
... and THAT makes it different from a ~b~I#define~N too!
.b9-14
.WN
~b~Itypedef char *STRING ~N
Here STRING is a pointer to a string and you may write ~b~ISTRING x;~N
meaning that ~b~Ix~N is a pointer to a ~b~Ichar~Nacter string.
~b~Itypedef int VECTOR[5] ~N
Here VECTOR is an array of 5 ~Iint~Ns and you may write
~b~IVECTOR x;~N so ~b~Ix~N is an array of 5 integers.
~b~Itypedef int INTEGER ~N
Here INTEGER is an int (of course!), and you may write ~b~IINTEGER x;~N
... and, when you compile your C program for a different computer
where ~b~Iint~N DATA TYPES are ~I4 bytes long~N (and you were counting on
their being only ~I2 bytes long~N!) you change this ~Ione~N statement to:
~b~Itypedef short INTEGER ~N meaning a "short" integer.
and all your references to ~b~IINTEGER x;~N and ~b~IINTEGER y;~N etc.
will be changed!
.WN
.T
That's all folks!
.K16,32
au revoir!
.q
#include <sugar.c>